package org.truenewx.tnxjeex.unit.support;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Map;
import javax.measure.*;

import org.truenewx.tnxjeex.unit.model.MeasureUnit;

public class MeasureUnitInvocationHandler<Q extends Quantity<Q>> implements MeasureUnit<Q>, InvocationHandler {

    private final Unit<Q> delegate;
    private String symbol;
    private final String name;
    private final String value;

    public MeasureUnitInvocationHandler(Unit<Q> delegate, String symbol, String name, String value) {
        this.delegate = delegate;
        this.symbol = symbol;
        this.name = name;
        this.value = value;
    }

    @Override
    public String getSymbol() {
        if (this.symbol != null) {
            return this.symbol;
        }
        String symbol = this.delegate.getSymbol();
        return symbol == null ? this.delegate.toString() : symbol;
    }

    @Override
    public String getName() {
        if (this.name != null) {
            return this.name;
        }
        return this.delegate.getName();
    }

    @Override
    public String getValue() {
        return this.value;
    }

    @Override
    public Dimension getDimension() {
        return this.delegate.getDimension();
    }

    @Override
    public Unit<Q> getSystemUnit() {
        return this.delegate.getSystemUnit();
    }

    @Override
    public Map<? extends Unit<?>, Integer> getBaseUnits() {
        return this.delegate.getBaseUnits();
    }

    @Override
    public boolean isCompatible(Unit<?> that) {
        return this.delegate.isCompatible(that);
    }

    @Override
    public boolean isEquivalentTo(Unit<Q> that) {
        return this.delegate.isEquivalentTo(that);
    }

    @Override
    public <T extends Quantity<T>> Unit<T> asType(Class<T> type) throws ClassCastException {
        return this.delegate.asType(type);
    }

    @Override
    public UnitConverter getConverterTo(Unit<Q> that) throws UnconvertibleException {
        return this.delegate.getConverterTo(that);
    }

    @Override
    public UnitConverter getConverterToAny(Unit<?> that) throws IncommensurableException, UnconvertibleException {
        return this.delegate.getConverterToAny(that);
    }

    @Override
    public Unit<Q> alternate(String symbol) {
        return this.delegate.alternate(symbol);
    }

    @Override
    public Unit<Q> shift(Number offset) {
        return this.delegate.shift(offset);
    }

    @Override
    public Unit<Q> shift(double offset) {
        return this.delegate.shift(offset);
    }

    @Override
    public Unit<Q> multiply(Number multiplier) {
        return this.delegate.multiply(multiplier);
    }

    @Override
    public Unit<Q> multiply(double multiplier) {
        return this.delegate.multiply(multiplier);
    }

    @Override
    public Unit<?> multiply(Unit<?> multiplier) {
        return this.delegate.multiply(multiplier);
    }

    @Override
    public Unit<?> inverse() {
        return this.delegate.inverse();
    }

    @Override
    public Unit<Q> divide(Number divisor) {
        return this.delegate.divide(divisor);
    }

    @Override
    public Unit<Q> divide(double divisor) {
        return this.delegate.divide(divisor);
    }

    @Override
    public Unit<?> divide(Unit<?> divisor) {
        return this.delegate.divide(divisor);
    }

    @Override
    public Unit<?> root(int n) {
        return this.delegate.root(n);
    }

    @Override
    public Unit<?> pow(int n) {
        return this.delegate.pow(n);
    }

    @Override
    public Unit<Q> transform(UnitConverter operation) {
        return this.delegate.transform(operation);
    }

    @Override
    public String toString() {
        return getKey();
    }

    @Override
    public Unit<Q> prefix(Prefix prefix) {
        return this.delegate.prefix(prefix);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        return method.invoke(this, args);
    }

}
